home *** CD-ROM | disk | FTP | other *** search
- /*
- elf_makeimage.c
- copyright 1996-1997 by Ben Martz
- all rights reserved world wide
-
- ANY AND ALL MODIFICATIONS TO THIS SOURCE MUST CREDIT THE ORIGINAL
- AUTHOR, BEN MARTZ (benmartz@ic.net), AND MUST BE GIVEN TO THE AUTHOR
- FOR INTEGRATION INTO THE MAIN PowerOS SOURCE TREE. THANK YOU FOR YOUR
- COOPERATION!
-
- This program takes a PowerPC ELF binary and converts it to an image
- that can be loaded into memory and executed directly.
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
-
- #include "elf_format.h"
-
- long elf_makeimage(char *fname, char **kptr);
-
- long elf_makeimage(char *fname, char **kptr) {
- char *kerneldata;
- char filename[256];
- OSErr err;
- FSSpec spec;
- FInfo fndrInfo;
- short file,count;
- long filelen, len, offset, i;
- char *filedata;
- Elf32_Hdr *header;
- Elf32_Shdr *sheader;
- UInt32 text_start = 0;
- UInt32 last_start = 0,last_offset,last_size;
- UInt32 sect_start = 0,sect_offset,sect_size;
- long totallen = 0;
-
- /* convert c to p str */
- strcpy(filename+1,fname);
- filename[0] = strlen(filename+1);
-
- /* open and read in the binary file */
- err = FSMakeFSSpec(0,0,(unsigned char *)filename,&spec);
- if(err != noErr) return -1;
-
- /* fix creator and type */
- err = FSpGetFInfo(&spec,&fndrInfo);
- if(err == noErr) {
- fndrInfo.fdType = 'elf ';
- fndrInfo.fdCreator = 'pos ';
- FSpSetFInfo(&spec,&fndrInfo);
- }
-
- err = FSpOpenDF(&spec,fsRdPerm,&file);
- if(err != noErr) return -1;
-
- err = GetEOF(file,&filelen);
- if(err != noErr) return -1;
-
- filedata = NewPtrClear(filelen);
- if(!filedata) return -1;
-
- len = filelen;
- err = FSRead(file,&len,filedata);
- if(err != noErr) return -1;
- if(len != filelen) return -1;
-
- FSClose(file);
-
- header = (Elf32_Hdr *) filedata;
-
- /* make sure that this is a binary file that we can handle! */
- if((header->ei_magic[1] != 'E') || (header->ei_magic[2] != 'L') || (header->ei_magic[3] != 'F')) return -1;
-
- if(header->ei_version != 1) return -1;
-
- if(header->e_machine != EM_PPC601) return -1;
-
- if(!header->e_shnum) return -1;
-
- /* find the program sections */
- /* read through once to find the memory size to allocate */
- last_start = last_offset = last_size = 0L;
- for(count = 0; count < header->e_shnum; count++) {
- sect_start = sect_offset = sect_size = 0L;
- offset = header->e_shoff + (header->e_shentsize * count);
- if(offset < (long)(filedata + filelen - sizeof(Elf32_Shdr))) {
- sheader = (Elf32_Shdr *) (filedata + offset);
- if(sheader->sh_type == SHT_PROGBITS) {
- sect_start = sheader->sh_addr;
- sect_offset = sheader->sh_offset;
- sect_size = sheader->sh_size;
-
- if(sect_start > last_start + last_size) {
- /* pad with zero */
- len = sect_start - (last_start + last_size);
- totallen += len;
- }
-
- if(sheader->sh_flags == SECT_TEXT) text_start = sect_start;
-
- len = sect_size;
- totallen += len;
-
- last_start = sect_start;
- last_offset = sect_offset;
- last_size = sect_size;
- }
- }
- }
-
- kerneldata = NewPtrClear(totallen);
- if(!kerneldata) return -1;
-
- *kptr = kerneldata;
-
- /* extract the sections now */
- totallen = 0;
- last_start = last_offset = last_size = 0L;
- for(count = 0; count < header->e_shnum; count++) {
- sect_start = sect_offset = sect_size = 0L;
- offset = header->e_shoff + (header->e_shentsize * count);
- if(offset < (long)(filedata + filelen - sizeof(Elf32_Shdr))) {
- sheader = (Elf32_Shdr *) (filedata + offset);
- if(sheader->sh_type == SHT_PROGBITS) {
- sect_start = sheader->sh_addr;
- sect_offset = sheader->sh_offset;
- sect_size = sheader->sh_size;
-
- if(sect_start > last_start + last_size) {
- /* pad with zero */
- len = sect_start - (last_start + last_size);
- totallen += len;
- while(len--) *((char *)(kerneldata++)) = '\0';
- }
-
- if(sheader->sh_flags == SECT_TEXT) text_start = sect_start;
-
- len = sect_size;
- totallen += len;
- for(i = 0; i < len; i++) {
- *((char *)(kerneldata++)) = *((char *) filedata+sect_offset+i);
- }
-
- last_start = sect_start;
- last_offset = sect_offset;
- last_size = sect_size;
- }
- }
- }
-
- return totallen;
- } /* end of main */